#include <stdio.h>

#include <stdlib.h>

#include "pCode.h"
	
int boolcontext = 0;
int callingfctboolcontext = 0;

//récupérer l'adresse de la variable
int pcodeGenAddressVar(TREE tree, VARSYM varSym, int diffLevel)
{
  if (tree == NULL)
    return 0;

  switch (tree->type) {

  case AT_ID:
    if (varSym->address < 0)
      {
	printf("ERROR : (!!) pcodeGenAddressVar : VAR '%d' has no location\n", tree->type);
	exit(1);
      }
    else if(strcmp(varSym->type,"bool")==0)
     { 
	printf("; loading ADDRESS of variable '%s'\n", tree->name);
	
	if(varSym->varMode == -1)
		printf("lda b %d %d\n",diffLevel, varSym->address+9+varSym->fct->nbArguments);

	//si c'est un argument (dans la fonction appelee)
	if(varSym->varMode != -1)
		printf("lda b 0 %d\n", varSym->address+5-varSym->fct->nbVar);

	boolcontext=1;
     }
    else if(strcmp(varSym->type,"int")==0)
     {
	printf("; loading ADDRESS of variable '%s'\n", tree->name);

	if(varSym->varMode == -1)
		printf("lda i %d %d\n",diffLevel, varSym->address+9+varSym->fct->nbArguments);

	//si c'est un argument (dans la fonction appelee)
	if(varSym->varMode != -1)
		printf("lda i 0 %d\n", varSym->address+5-varSym->fct->nbVar);

	boolcontext = 0;

     }
    else if(strcmp(varSym->type,"matrix")==0) 
     {
	if(varSym->varMode == -1)
		printf("lda a %d %d\n", diffLevel, varSym->address+9+varSym->fct->nbArguments);

	if(varSym->varMode!= -1)
		printf("lda a 0 %d\n", varSym->address+5-varSym->fct->nbVar);
     }
	

    break;

  default:
    printf("ERROR : unrecognized type=%s in pcodeGenAddressVar(..)\n", tree->name);
    exit(1);
  }

  return 0;
}

int pcodeGenValue(TREE tree, FCTSYM symTable)
{ 
  int location; 
  static int position =0;
  static int staticlabel = 0;
  int label = staticlabel;
  int diffLevel = 0;
  int decalage = 0;
  int compteur = 0; //compteur pour parcourir toutes les variables d'une fonction
  VARSYM var = NULL;
  VARSYM var2 = NULL;
  FCTSYM fct = NULL;
  FCTSYM temp = NULL;
  static FCTSYM fctcalled = NULL;
  staticlabel++;
  
	

  if (tree == NULL)
    return 0;

  switch (tree->type) {
  
  case AT_ROOT: //à la racine
	printf("mst 0\n");
	printf("cup 0 @%s\n", tree->name);//on considere le main comme une fonction de niveau 0

	if(tree->middle->type == AT_FCT)
		pcodeGenValue(tree->middle,symTable->childFct);
	else
    		pcodeGenValue(tree->middle,symTable);
    	printf("; end of program\n");
    break;
	
  case AT_LISTFCT: //la liste des fonctions globales
	fct = (FCTSYM) searchFctAtParentFct(symTable, tree->left->name);
	pcodeGenValue(tree->left,fct);

	if(tree->middle->type == AT_FCT)//la derniere fonction du meme niveau se trouve en tree->middle sans passer par un noeud AT_LISTFCT
	{
		fct = (FCTSYM) searchFctAtParentFct(symTable, tree->middle->name);
		pcodeGenValue(tree->middle,fct);
	}
	else
		pcodeGenValue(tree->middle,symTable);
    break;

  case AT_RETURN: 
	printf(";begin of return \n");
	if(callingfctboolcontext==0)
	{
		printf("lda i 0 0\n");
	}
	else
	{
		printf("lda b 0 0\n");
	}

	pcodeGenValue(tree->left, symTable);

	printf(";boolcontext: %d\n",boolcontext);

	if(boolcontext==0)
	{
		if(tree->left->type == AT_ID)
			printf("ind i\n");
		printf("sto i\n");
	}
	else
	{
		if(tree->left->type == AT_ID)
			printf("ind b\n");
		printf("sto b\n");
	}
	printf("; end of return\n");
    break;
	
  case AT_FCT: //fonction
	pcodeGenValue(tree->right,symTable);//partie declaration
	printf("define @%s\n", tree->name);

	printf("ssp %d\n", symTable->nbVar+9+symTable->nbArguments);//3 pour le swap et modulo et 5 pour le mst + 1 sinon out of stack + le nombre de variables

	printf(";name fonction: %s, main?%d\n",symTable->name, symTable->isMain);

    	pcodeGenValue(tree->other,symTable);//aller voir dans le code
	if(symTable->isMain!=1)
	{
		if(strcmp(tree->middle->name,"int")==0 || strcmp(tree->middle->name,"bool")==0)
			printf("retf\n");//return fonction
		else if(strcmp(tree->middle->name,"nil")==0)
			printf("retp\n");//return procedure
	}
	else
		printf("stp\n");//une fois le main execute, le programme est fini
    break;

  case AT_DECL: //bloc de declarations
	if(symTable->childFct!=NULL) //pas la peine de générer du pcode si pas de fonctions
	{
		pcodeGenValue(tree->left,symTable);//fonction fille
	}
    break;

  case AT_CODE: //code d'une fonction
    	pcodeGenValue(tree->left,symTable);
    break;
	
  case AT_ILISTCODE: //liste d'instructions de code
	pcodeGenValue(tree->left,symTable);
	
    	pcodeGenValue(tree->middle,symTable);
    break;

  case AT_ILISTDECL: //liste d'instructions de declaration
	if(tree->left != NULL)
	{
		if(tree->left->type == AT_FCT)//si c'est une fonction, on va dans les fonctions filles et on génère le code de la fonction en question
		{
			fct = (FCTSYM) searchFctAtParentFct(symTable, tree->left->name);
			pcodeGenValue(tree->left,fct);
		}
	}
	if(tree->middle!= NULL)
	{
		pcodeGenValue(tree->middle,symTable);
	}
    break;
	
  case AT_CALLFCT: //liste d'appels de fonctions
	printf("mst 0\n");
	fct = (FCTSYM) searchFctAtParentFct(symTable, tree->left->name);
	
	if(tree->middle!=NULL && fct!=NULL)
		{
		fctcalled = fct;
		position = fct->nbArguments;
		pcodeGenValue(tree->middle, symTable); // Loader les arguments
		}

	if(fct!= NULL)
		printf("cup %d @%s\n",fct->nbArguments, tree->left->name);//cup (nbre d'arguments qu'on passe) (nom de la fonction appelee)
	else
	{
		FCTSYM temp;
		temp = symTable;
		
		while(temp->parentFct != NULL && fct == NULL)
		{
			temp = temp->parentFct;
			fct = (FCTSYM) searchFctAtParentFct(temp, tree->left->name);
			if(tree->middle!=NULL && fct!=NULL)//verifier si la fonction a des arguments
			{	
				position = fct->nbArguments;
				fctcalled = fct;
				pcodeGenValue(tree->middle, symTable);  // Loader les arguments
			}
			if(fct!= NULL)
				printf("cup %d @%s\n",fct->nbArguments, tree->left->name);//cup (nbre d'arguments qu'on passe) (nom de la fonction appelee)
		}
	}
    break;
	
  case AT_LISTCALLARG: //liste d'arguments
    	pcodeGenValue(tree->left,symTable);
	if(tree->middle != NULL)//s'il y a encore des arguments
    		pcodeGenValue(tree->middle,symTable);
    break;
	
  case AT_CALLARG: //argument
	pcodeGenValue(tree->left,symTable);
	if(tree->left->type == AT_ID)//si l'argument qu'on passe est une simple variable (avec passage par valeur), on recupere sa valeur
	{	
		var = searchVarAtFctByPos(fctcalled, position); 
		position--;
		if(var->varMode!=1)
		{
		
			if(boolcontext == 0)
				printf("ind i\n");
			else 
				printf("ind b\n");
		}
	}
    break;

  case AT_ID: // variable
	var = (VARSYM) searchVarAtFct(symTable,tree->name);
	if(var!=NULL)
	{
		pcodeGenAddressVar(tree,var,diffLevel);
		if(var->varMode == 1)
			printf("ind a\n");
	}
	else //si on la trouve pas dans la fonction, on cherche dans les fonctions englobantes
	{
		FCTSYM temp;
		temp = symTable;
		while(temp->parentFct!=NULL && var==NULL)
		{
			temp = temp->parentFct;
			var = (VARSYM) searchVarAtFct(temp,tree->name);
			diffLevel++;
		}
		printf(";variable: %s - num: %d\n",var->name, var->address);
		pcodeGenAddressVar( tree,var, diffLevel);
		if(var->varMode == 1)
			printf("ind a\n");
	}

    break;

  case AT_NBPOS: // positive number
    	printf("; loading constant integer value '%d'\n", tree->value);
    	printf("ldc i %d\n", tree->value);//ldc=load constant i: charge une valeur constante entière

    break;
	
  case AT_NBNEG: // negative number
    	printf("; loading constant integer value '%d'\n", tree->value);
    	printf("ldc i %d\n", tree->value);
    break;
	
  case AT_BOOL: // boolean
   	printf("; loading constant boolean value '%d'\n", tree->value);
    	printf("ldc b %d\n", tree->value);//ldc=load constant b: charge une valeur constante booleenne 1->true, 0->false
    	boolcontext = 1;
    break;
	
  case AT_AFFECTL: //affectation (gauche et droite)
    	printf("\n; begin of affectation left %d\n", label);
	boolcontext = 0;
	pcodeGenValue(tree->left, symTable);
	callingfctboolcontext = boolcontext;
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID && boolcontext==0)
		printf("ind i\n");
	else if(tree->middle->type == AT_ID && boolcontext==1)
		printf("ind b\n");
   	(callingfctboolcontext == 1)? printf("sto b\n"): printf("sto i\n");//sto=store
   	printf("; end of affectation left %d\n", label);
	boolcontext=0;
    break;
	
  case AT_SWAP: //swap
    	printf("\n; begin of swap %d\n", label);
	if(boolcontext == 0)
	{
	printf("lda i 0 %d\n", 7+symTable->nbArguments);//2+5 du mst
	pcodeGenValue(tree->left,symTable);
	printf("ind i\n");
	printf("sto i\n");
	pcodeGenValue(tree->left, symTable);
	pcodeGenValue(tree->middle, symTable);
	printf("ind i\n");
	printf("sto i\n");
	pcodeGenValue(tree->middle, symTable);
	printf("lda i 0 %d\n", 7+symTable->nbArguments);
	printf("ind i\n");
	printf("sto i\n");
	}
	else if (boolcontext == 1)
	{
	printf("lda b 0 %d\n", 7+symTable->nbArguments);
	pcodeGenValue(tree->left,symTable);
	printf("ind b\n");
	printf("sto b\n");
	pcodeGenValue(tree->left, symTable);
	pcodeGenValue(tree->middle, symTable);
	printf("ind b\n");
	printf("sto b\n");
	pcodeGenValue(tree->middle, symTable);
	printf("lda b 0 %d\n", 7+symTable->nbArguments);
	printf("ind b\n");
	printf("sto b\n");
	}
	printf("; end of swap %d\n", label);
    break;

  case AT_IF:
	
	pcodeGenValue(tree->left, symTable);//verifier l'expression booleenne
	if(tree->left->type == AT_ID)
		printf("ind b\n");
	printf("not b\n");
	printf("fjp @condition_ok_%d\n",label);//forward jump = jump conditionnel
	if(tree->right!=NULL)
	{
		boolcontext = 0;
		pcodeGenValue(tree->right, symTable);
	}
	printf("ujp @endif_%d\n",label);//unconditionnal jump = jump sans condition
	printf("define @condition_ok_%d\n",label);
	if(tree->middle != NULL){
		boolcontext  = 0;
		pcodeGenValue(tree->middle, symTable);
		
	}
	printf("define @endif_%d\n",label);
    break;

  case AT_WHILE:
	printf("define @whiletest_%d \n", label);
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
	{
		printf("ind b\n");
	}
	printf("not b\n");
	printf("fjp @while_ok_%d\n", label);
	printf("ujp @whileend_%d\n",label);

	printf("define @while_ok_%d\n",label);
	if(tree->middle != NULL)
	{
		boolcontext = 0;
		pcodeGenValue(tree->middle, symTable);
	}
	printf("ujp @whiletest_%d \n",label);
	printf("define @whileend_%d\n",label);
    break;

  //!!!!!!!!!!!!!Operateurs sur les entiers!!!!!!!!!!!!!!!!!
  case AT_ADD: // sum
    	printf("\n; begin of sum %d\n", label);
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
		printf("ind i\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
		printf("ind i\n");
    	printf("add i\n");
   	printf("; end of sum %d\n", label);
    break;

  case AT_MIN: // substraction
    	printf("\n; begin of substraction %d\n", label); 
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
	printf("ind i\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
	printf("ind i\n");
    	printf("sub i\n");
    	printf("; end of substraction %d\n", label);
    break;

  case AT_MUL: // multiplication
	printf("\n; begin of multiplication %d\n", label);
	pcodeGenValue(tree->left, symTable);
 	if(tree->left->type == AT_ID)
	printf("ind i\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
	printf("ind i\n");
	printf("mul i\n");
	printf("; end of the multiplication %d\n", label);
    break;
	
  case AT_DIV: // division
	printf("\n; begin of multiplication %d\n", label);
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
	printf("ind i\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
	printf("ind i\n");
	printf("div i\n");
	printf("; end of the multiplication %d\n", label);
    break;

  case AT_OUT: // print
    	printf("\n; begin of print %d\n", label);
   	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
		printf("ind i\n");
    	printf("prin\n");
    	printf("; end of print %d\n", label);
    break;

  case AT_IN: // read
    	printf("\n; begin of read %d\n", label);
    	printf("read\n");
   	printf("; end of read %d\n", label);
    break;

  case AT_MOD: //modulo

    /* x mod y  (x,y >= 0)
     *   put y into cell 1 so we can easily remember it
     *   put x into cell 0 so we can easily update it
     *
     * x mod y = 'ERROR' if (y==0)
     *           'x after while !(x < y) x := x-y' else
     */

    printf("\n; begin of modulo %d\n", label);

    printf("\n; saves computed arguments\n");

    /* x */
    printf("; saving x value\n");
    printf("lda i 0 %d\n", 5+symTable->nbArguments);//0+5 du mst + le nombre d'arguments
    pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
	printf("ind i\n");
    printf("sto i\n");
    printf("; done with saving x value\n\n");

    /* y */
    printf("; saving y value\n");
    printf("lda i 0 %d\n", 6+symTable->nbArguments);
    pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
	printf("ind i\n");
    printf("sto i\n");
    printf("; done with saving y value\n\n");

    /* checks if y == 0 */
    printf("\n; checks if y == 0\n");
    printf("lda i 0 %d\n", 6+symTable->nbArguments);
    printf("ind i\n");
    printf("ldc i 0\n");
    printf("equ i\n");
    printf("fjp @mod_not_zero_%d\n", label);
    
    /* here y == 0 */
    printf("; mod division by 0 !!\n");
    printf("stp\n");

    /* else y != 0 */
    printf("\n; begin of mod inner loop\n");
    printf("define @mod_not_zero_%d\n",label);
    
    /* checks if x < y  */
    printf("\n; !(x < y) ?\n");
    printf("lda i 0 %d\nind i\n", 5+symTable->nbArguments);
    printf("lda i 0 %d\nind i\n", 6+symTable->nbArguments);
    printf("les i\n");
    printf("not b\n");
    printf("fjp @mod_end_%d\n",label);

    /* !(x<y) -> x := x-y ; goto @mod_not_zero_%d */
    printf("\n; loop body : x := x-y\n");
    printf("lda i 0 %d\n", 5+symTable->nbArguments);
    printf("lda i 0 %d\nind i\n", 5+symTable->nbArguments);
    printf("lda i 0 %d\nind i\n", 6+symTable->nbArguments);
    printf("sub i\n");
    printf("sto i\n");

    printf("ujp @mod_not_zero_%d\n", label);
    
    /* end -> put mod result on top of the stack */
    printf("\n; end, put result on top of the stack\n");
    printf("define @mod_end_%d\n",label);
    printf("lda i 0 %d\nind i\n", 5+symTable->nbArguments);
    
    printf("\n; end of modulo %d\n", label);

    break;
	
  case AT_EQUAL:
  	printf("\n; begin of equal %d\n", label);
	boolcontext = 1;
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
		printf("ind i\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
		printf("ind i\n");
	printf("equ i\n");
	boolcontext = 1;
	printf("\n; end of equal %d\n", label);
	break;
	
  case AT_SMALLER:
  	printf("\n; begin of smaller %d\n", label);
	boolcontext = 1;
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
		printf("ind i\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
		printf("ind i\n");
	printf("les i\n");
	boolcontext = 1;
	printf("\n; end of smaller %d\n", label);

	break;
	
  case AT_GREATER:
  	printf("\n; begin of greater %d\n", label);
	boolcontext = 1;
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
		printf("ind i\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
		printf("ind i\n");
	printf("grt i\n");
	boolcontext = 1;
	printf("\n; end of greater %d\n", label);
	break;
	
  case AT_SMALLEQ:
  	printf("\n; begin of less or equal %d\n", label);
	boolcontext = 1;
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
		printf("ind i\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
		printf("ind i\n");
	printf("leq i\n");
	boolcontext = 1;
	printf("\n; end of less or equal %d\n", label);

    break;

  case AT_GREATEQ:
  	printf("\n; begin of greater or equal %d\n", label);
	boolcontext = 1;
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
		printf("ind i\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
		printf("ind i\n");
	printf("geq i\n");
	boolcontext = 1;
	printf("\n; end of greater or equal %d\n", label);

	break;
  //!!!!!!!!!!!!!Fin operateurs sur les entiers!!!!!!!!!!!!!!!!!

  //!!!!!!!!!!!!!Operateurs sur les booleens!!!!!!!!!!!!!!!!!
  

case AT_AND:
  	printf("\n; begin of AND %d\n", label);
	boolcontext = 1;
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
		printf("ind b\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
		printf("ind b\n");
	printf("and b\n");
	boolcontext = 1;
	printf("\n; end of AND %d\n", label);
	
	break;
	
  case AT_OR:
  	printf("\n; begin of OR %d\n", label);
	boolcontext = 1;
	pcodeGenValue(tree->left, symTable);
	if(tree->left->type == AT_ID)
		printf("ind b\n");
	pcodeGenValue(tree->middle, symTable);
	if(tree->middle->type == AT_ID)
		printf("ind b\n");
	printf("or b\n");
	boolcontext = 1;
	printf("\n; end of OR %d\n", label);
	break;
	
  case AT_NOT:
  
	printf("\n; begin of not %d\n", label);
	pcodeGenValue(tree->left,symTable);
	if(tree->left->type == AT_ID)
		printf("ind b\n");
	printf("not b\n");
	printf("\n; end of not %d\n", label);
	
	break;
  //!!!!!!!!!!!!!Fin operateurs sur les booleens!!!!!!!!!!!!!!!!!
  
  //!!!!!!!!!!!!!Operateurs sur les matrices!!!!!!!!!!!!!!!!!

  case AT_CREATE://3 arguments: une matrice et 2 entiers, initialise tous les elements a 0
  	printf("\n; begin of create %d\n", label);

	//loader le nombre de lignes et les copier dans un autre emplacement de la stack
	printf("lda i 0 %d\n", 5+symTable->nbArguments);
	pcodeGenValue(tree->right, symTable);//troisième argument: un entier (nb lignes)
	if(tree->middle->type == AT_ID)
		printf("ind i\n");

	printf("sto i\n");

	//loader le nombre de colonnes et les copier dans un autre emplacement de la stack
	printf("lda i 0 %d\n", 6+symTable->nbArguments);
	pcodeGenValue(tree->middle, symTable);//deuxième argument: un entier (nb colonnes)
	if(tree->right->type == AT_ID)
		printf("ind i\n");

	printf("sto i\n");

	pcodeGenValue(tree->left, symTable);//premier argument: la matrice

	printf("lda i 0 %d\n", 5+symTable->nbArguments);
	printf("ind i\n");
	printf("lda i 0 %d\n", 6+symTable->nbArguments);
	printf("ind i\n");	

	printf("mul i\n");
	printf("ldc i 2\n");//pour stocker le nombre de lignes et le nombre de colonnes dans le heap
	printf("add i\n");

	printf("new\n");//alloue de l'espace sur le heap

	//stocker le nombre de lignes de la matrice dans le heap
	pcodeGenValue(tree->left, symTable);//premier argument: la matrice//lda a 
	printf("ind a\n");
	printf("lda i 0 %d\n", 5+symTable->nbArguments);//emplacement reserve pour le modulo habituellement
	printf("ind i\n");
	printf("sto i\n");

	pcodeGenValue(tree->left, symTable);//premier argument: la matrice//lda a 
	printf("ind a\n");
	printf("ldc i 1\n");//decalage par rapport a l'adresse du pointeur (heap)
	printf("ixa 1\n");

	//stocker le nombre de colonnes de la matrice dans le heap
	printf("lda i 0 %d\n", 6+symTable->nbArguments);//emplacement reserve pour le modulo habituellement
	printf("ind i\n");
	printf("sto i\n");

	//DEBUT DU WHILE!!!!!!!!!!!!!!!!!


	//initialiser le compteur et le stocker dans la stack
	printf("lda i 0 %d\n", 7+symTable->nbArguments);//le compteur se trouve a l'adresse 7 (localement)+nombre d'arguments, utilisation de l'emplacement reserve au swap
	printf("ldc i 2\n");//on commence a l'element 2 car les elements 0 et 1 sont le nombre de lignes et de colonnes
	printf("sto i\n");

	//boucler sur tous les elements de la matrice et les initialiser a 0
	printf("define @whileinitmatrix_%d \n", label);
	
	//loader la valeur du compteur
	printf("lda i 0 %d\n", 7+symTable->nbArguments);
	printf("ind i\n");

	//compter le nombre d'elements de la matrice
	printf("lda i 0 %d\n", 5+symTable->nbArguments);
	printf("ind i\n");
	printf("lda i 0 %d\n", 6+symTable->nbArguments);
	printf("ind i\n");	
	printf("mul i\n");
	printf("ldc i 2\n");
	printf("add i\n");
	
	printf("les i\n");//tant que mon compteur est plus petit que le nombre total d'elements

	printf("not b\n");
	printf("fjp @while_ok_%d\n", label);
	printf("ujp @whileend_%d\n",label);

	printf("define @while_ok_%d\n",label);

	//tant que la condition est verifiee
	pcodeGenValue(tree->left, symTable);//premier argument: la matrice//lda a 
	printf("ind a\n");

	printf("lda i 0 %d\n", 7+symTable->nbArguments);
	printf("ind i\n");//decalage dans le heap
	printf("ixa 1\n");

	//stocker la valeur 0 dans l'element du heap
	printf("ldc i 0\n");
	printf("sto i\n");
	
	//incrementer le compteur
	printf("lda i 0 %d\n", 7+symTable->nbArguments);

	printf("lda i 0 %d\n", 7+symTable->nbArguments);
	printf("ind i\n");
	printf("ldc i 1\n");
	printf("add i\n");
	printf("sto i\n");

	printf("ujp @whileinitmatrix_%d \n",label);
	printf("define @whileend_%d\n",label);
	
	
	printf("\n; end of create %d\n", label);
	break;
	
  case AT_SET://affecte une valeur a un element particulier d'une matrice  	
	printf("\n; begin of set %d\n", label);
	
	pcodeGenValue(tree->left, symTable);//premier argument: la matrice//lda a 
	printf("ind a\n");

	printf("lda i 0 %d\n", 5+symTable->nbArguments);
	pcodeGenValue(tree->right, symTable);//troisième argument: la ligne
	if(tree->middle->type == AT_ID)
		printf("ind i\n");
	printf("sto i\n");

	printf("lda i 0 %d\n", 6+symTable->nbArguments);
	pcodeGenValue(tree->middle, symTable);//deuxième argument: la colonne
	if(tree->right->type == AT_ID)
		printf("ind i\n");
	printf("sto i\n");

	//calculer l'empacement auquel correspond la "case" de la matrice dans le heap
	//numero de la colonne (dans la stack)
	printf("lda i 0 %d\n", 6+symTable->nbArguments);
	printf("ind i\n");

	//numero de la ligne (dans la stack)
	printf("lda i 0 %d\n", 5+symTable->nbArguments);
	printf("ind i\n");
	
	printf("ldc i 1\n");
	printf("sub i\n");

	//nbre total de colonnes (dans le heap)
	pcodeGenValue(tree->left, symTable);//premier argument: la matrice//lda a 
	printf("ind a\n");
	printf("ldc i 1\n");
	printf("ixa 1\n");
	printf("ind i\n");

	printf("mul i\n");
	printf("add i\n");//formule: numeroColonne + (numeroLigne-1)*nbreTotalColonnes
	
	//ajouter 2 pour le nombre total de ligne et de colonnes qui se trouvent au 2 premiers emplacements du heap et retirer 1 car le heap commence à l'adresse 0 (localement) tandis qu'on compte le nombre de lignes et de colonnes à partir de 1 dans les matrices en lsd11
	printf("ldc i 1\n");
	printf("add i\n");

	printf("ixa 1\n");

	pcodeGenValue(tree->other, symTable);//quatrieme argument: le nombre
	if(tree->other->type == AT_ID)
		printf("ind i\n");

	printf("sto i\n");

	printf("\n; end of set %d\n", label);
	break;

  case AT_GET:
  	printf("\n; begin of get %d\n", label);

	pcodeGenValue(tree->left, symTable);//premier argument: la matrice//lda a 
	printf("ind a\n");

	printf("lda i 0 %d\n", 5+symTable->nbArguments);
	pcodeGenValue(tree->right, symTable);//troisième argument: la ligne
	if(tree->middle->type == AT_ID)
		printf("ind i\n");
	printf("sto i\n");

	printf("lda i 0 %d\n", 6+symTable->nbArguments);
	pcodeGenValue(tree->middle, symTable);//deuxième argument: la colonne
	if(tree->right->type == AT_ID)
		printf("ind i\n");
	printf("sto i\n");

	//calculer l'empacement dans le heap
	//numero de la colonne (dans la stack)
	printf("lda i 0 %d\n", 6+symTable->nbArguments);
	printf("ind i\n");

	//numero de la ligne (dans la stack)
	printf("lda i 0 %d\n", 5+symTable->nbArguments);
	printf("ind i\n");
	
	printf("ldc i 1\n");
	printf("sub i\n");

	//nbre total de colonnes (dans le heap)
	pcodeGenValue(tree->left, symTable);//premier argument: la matrice//lda a 
	printf("ind a\n");
	printf("ldc i 1\n");//le nombre total de colonnes est le deuxième élément
	printf("ixa 1\n");
	printf("ind i\n");

	printf("mul i\n");
	printf("add i\n");//formule: numeroColonne + (numeroLigne-1)*nbreTotalColonnes
	
	//ajouter 2 pour le nombre total de ligne et de colonnes qui se trouvent au 2 premiers emplacements du heap et retirer 1 car le heap commence à l'adresse 0 (localement) tandis qu'on compte le nombre de lignes et de colonnes à partir de 1 dans les matrices en lsd11
	printf("ldc i 1\n");
	printf("add i\n");

	printf("ixa 1\n");

	printf("ind i\n");
	
	printf("\n; end of get %d\n", label);

	break;
	
  case AT_CLONE://dupliquer une matrice (copie son contenu dans une autre)
  	printf("\n; begin of clone %d\n", label);

	//Avant le debut du clone proprement dit, il faut réserver les emplacements dans le heap pour la nouvelle matrice

	//récupérer le nombre de lignes et le nombre de colonnes de la première matrice
	
	printf("lda i 0 %d\n", 5+symTable->nbArguments);//l'emplacement dans la stack qui contiendra le nombre de lignes

	//nbre total de lignes de la première matrice (dans le heap)
	pcodeGenValue(tree->left, symTable);//premier argument: premiere matrice//lda a 
	printf("ind a\n");
	printf("ind i\n");
	printf("sto i\n");

	printf("lda i 0 %d\n", 6+symTable->nbArguments);//l'emplacement dans la stack qui contiendra le nombre de colonnes

	//nbre total de colonnes de la première matrice (dans le heap)
	pcodeGenValue(tree->left, symTable);//premier argument: premiere matrice//lda a 
	printf("ind a\n");
	printf("ldc i 1\n");
	printf("ixa 1\n");
	printf("ind i\n");
	printf("sto i\n");

	//créer la 2ème matrice

	pcodeGenValue(tree->middle, symTable);//étant donné que pour la deuxième matrice, c'est la première fois qu'on l'utilise, il faut d'abord faire un pcodeGenAddressVar (car le type du fils middle est AT_ID)

	//on reload le nombre de lignes et le nombres de colonnes
	printf("lda i 0 %d\n", 5+symTable->nbArguments);
	printf("ind i\n");
	printf("lda i 0 %d\n", 6+symTable->nbArguments);
	printf("ind i\n");	

	printf("mul i\n");
	printf("ldc i 2\n");//pour stocker le nombre de lignes et le nombre de colonnes dans le heap
	printf("add i\n");

	printf("new\n");//alloue de l'espace sur le heap

	//stocker le nombre de lignes de la matrice dans le heap
	pcodeGenValue(tree->middle, symTable);//premier argument: 2ème matrice//lda a 
	printf("ind a\n");
	printf("lda i 0 %d\n", 5+symTable->nbArguments);//emplacement reserve pour le modulo habituellement
	printf("ind i\n");
	printf("sto i\n");

	pcodeGenValue(tree->middle, symTable);//premier argument: 2ème matrice//lda a 
	printf("ind a\n");
	printf("ldc i 1\n");//decalage par rapport a l'adresse du pointeur (heap)
	printf("ixa 1\n");

	//stocker le nombre de colonnes de la matrice dans le heap
	printf("lda i 0 %d\n", 6+symTable->nbArguments);//emplacement reserve pour le modulo habituellement
	printf("ind i\n");
	printf("sto i\n");
	

	//DEBUT DU WHILE!!!!!!!!!!!!!!!!!


	//initialiser le compteur et le stocker dans la stack
	printf("lda i 0 %d\n", 7+symTable->nbArguments);//le compteur se trouve a l'adresse 7 + nombre d'arguments (localement), utilisation de l'emplacement reserve au swap
	printf("ldc i 2\n");
	printf("sto i\n");

	//boucler sur tous les elements de la matrice et les initialiser a 0
	printf("define @whileclonematrix_%d \n", label);
	
	//loader la valeur du compteur
	printf("lda i 0 %d\n", 7+symTable->nbArguments);
	printf("ind i\n");

	//compter le nombre d'elements de la matrice
	//nbre total de lignes (dans le heap)
	pcodeGenValue(tree->left, symTable);//premier argument: premiere matrice//lda a 
	printf("ind a\n");
	printf("ind i\n");
	//nbre total de colonnes (dans le heap)
	pcodeGenValue(tree->left, symTable);//premier argument: premiere matrice//lda a 
	printf("ind a\n");
	printf("ldc i 1\n");
	printf("ixa 1\n");
	printf("ind i\n");
	//on multiplie et on ajoute 2	
	printf("mul i\n");
	printf("ldc i 2\n");
	printf("add i\n");
	
	printf("les i\n");//tant que mon compteur est plus petit que le nombre total d'elements

	printf("not b\n");
	printf("fjp @while_ok_%d\n", label);
	printf("ujp @whileend_%d\n",label);

	printf("define @while_ok_%d\n",label);	//tant que la condition est verifiee


	//charger la nouvelle matrice et son emplacement à initialiser
	pcodeGenValue(tree->middle, symTable);//premier argument: 2ème matrice//lda a 
	printf("ind a\n");
	printf("lda i 0 %d\n", 7+symTable->nbArguments);
	printf("ind i\n");
	printf("ixa 1\n");//on prépare l'emplacement

	//on va chercher la valeur dans la premiere matrice
	pcodeGenValue(tree->left, symTable);//premier argument: premiere matrice//lda a 
	printf("ind a\n");
	//récupérer la valeur de l'élément
	printf("lda i 0 %d\n", 7+symTable->nbArguments);
	printf("ind i\n");//on récupère la valeur du compteur
	printf("ixa 1\n");
	printf("ind i\n");//on récupère la valeur de l'élément

	//stocker la valeur dans la nouvelle matrice
	printf("sto i\n");

	//incrementer le compteur
	printf("lda i 0 %d\n", 7+symTable->nbArguments);

	printf("lda i 0 %d\n", 7+symTable->nbArguments);
	printf("ind i\n");
	printf("ldc i 1\n");
	printf("add i\n");
	printf("sto i\n");

	printf("ujp @whileclonematrix_%d \n",label);
	printf("define @whileend_%d\n",label);

	printf("\n; end of clone %d\n", label);
  
	break;

  //!!!!!!!!!!!!!Fin operateurs sur les matrices!!!!!!!!!!!!!!!!!

  default:
	break;
  }

  return 0;
}








